class GcalController < ApplicationController
  
  include GcalHelper
  layout 'gcal'
  
  $login = "core/templates/login"
  $super_logout = "users/templates/logout"
  $logout = "users/templates/logout"
  
  # The following names are the ones given to the different types of seminars
  # this is how the queries should be done !!!!!!!!
  $seminar_event = "Seminar"
  $PhD_defense = "PhD Defense"
  $PhD_seminar = "PhD Seminar"
  $Defense = "Defense"
  $General_event = "General event"
  $class_room_event = "class_room"
  
  $room_003 = "http://www.google.com/calendar/feeds/vtj0r7h12jfpjvkcagddaam3jc%40group.calendar.google.com/public/basic"
  $room_004 = "http://www.google.com/calendar/feeds/4uldjdn9bf00aqger105crd5bc%40group.calendar.google.com/public/basic"
  $room_006 = "http://www.google.com/calendar/feeds/rkm9cupl0js8rinfmrtvek9714%40group.calendar.google.com/public/basic"
  $room_007 = "http://www.google.com/calendar/feeds/7ms1f85tgr02ho81m7n6s28scs%40group.calendar.google.com/public/basic"
  $room_008 = "http://www.google.com/calendar/feeds/juuikibcrm8rqaut36bn0n6i6g%40group.calendar.google.com/public/basic"
  $room_013 = "http://www.google.com/calendar/feeds/8fu02csfbnnpfl7c08tg2r3ac8%40group.calendar.google.com/public/basic"
  $room_015 = "http://www.google.com/calendar/feeds/9c0pau6pncdto0dspekqajcua8%40group.calendar.google.com/public/basic"
  
  $seminars = "http://www.google.com/calendar/feeds/2l0tnq664qab4glrn3kstte46s%40group.calendar.google.com/public/basic"
  
  $all_day = "gcal/templates/mains/all_day"

  $classes = ["SI-003", "SI-004", "SI-006", "SI-007", "SI-008", "SI-013", "SI-015"]
  $roomUrls = [$room_003, $room_004, $room_006, $room_007, $room_008, $room_013, $room_015]

  #Function incharge of connecting to Google calendar directly.
  def index
    
    flag = params[:flag].to_s
    
    if(flag == "All")  
      @response_from_rooms = get_class_events
      @response_from_seminars = get_seminars(@response_from_rooms)
    elsif(flag == "Class")
      @response_from_rooms = get_class_events
      @response_from_seminars = ""
    elsif(flag == "Seminar")
      @response_from_rooms = ""
      @response_from_seminars = get_seminars(@response_from_rooms)
    elsif(flag == "is_a_Change")
      @success =  get_class_events
      get_seminars(@success)
      return render :partial => 'core/templates/change_response'
    end
    
    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @gcal }
    end
  end
  
  
  #Function in charge of getting all the events related to the classroom.
  #I decided to leave it this big in order to make it more readable. It has to main areas first where we keep looping until
  #we know for sure we received something from the google calendar and is not empty(an emoty response can happened but not in all the classrooms)
  #Then the second area is the creation of events if the response was not empty and the recheck of some of the classrooms
  #which their response was empty
  def get_class_events
    @is_a_good_connection = false
    @all_empty_responses = true
    empty_responses_places = Array.new
    empty_array_counter = 0
    

      for counter in 0..$classes.length-1 
        @event_hash = readxml($roomUrls[counter])
        
        if(@event_hash.length > 0)
          @all_empty_responses = false
          
          @event_hash = clear_and_create_events(@event_hash, $classes[counter])
          @event_hash.clear
          puts "Got good response from class: "+$classes[counter].to_s
        else
          puts "Trying to get information, the result was empty for class "+$classes[counter].to_s
          empty_responses_places[empty_array_counter] = counter
          empty_array_counter += 1
          puts "Now empty responses size is: "+empty_responses_places.length.to_s+" in position "+(empty_array_counter-1).to_s
        end
      end
      
      #in this area we check wether all the responses are good or some of them are empty
      #If some are empty the we chek it one more time
      if((not @all_empty_responses)&&(empty_responses_places.length == 0))
          puts "Responses for every single class were good"
          @is_a_good_connection = true
      elsif(not @all_empty_responses)
           puts "Some responses for classes were empty"
           for counter in 0..empty_array_counter-1
             puts "HERE is an ERROR : "+empty_responses_places[counter].to_s
             @event_hash = readxml($roomUrls[empty_responses_places[counter]])
             @event_hash = clear_and_create_events(@event_hash, $classes[counter])
             @event_hash.clear
           end
           @is_a_good_connection = true
      end

    return @is_a_good_connection
  end
  
  
  #Smae idea as get the classroom events the only difference is we dont have an array of different places for the Seminars
  def get_seminars(class_room_answer)
    @is_a_good_connection = false
    @event_hash = readxml($seminars)
      
      if(@event_hash.length > 0) 
        puts "Seminars query were good, ready to continue"
        clear_and_create_seminars(@event_hash)
        @is_a_good_connection = true
     
      #the next block we check if the response in the rooms was good.
      #If the room reponse ws good this means that either the connection in the seminars went wrong or there is no event schedule
      elsif(class_room_answer)
        @event_hash = readxml($seminars)
        if(@event_hash.length > 0) 
          clear_and_create_seminars(@event_hash)
          @is_a_good_connection = true
        end
        
      end
   
    return @is_a_good_connection
  end
  
  
  #Here is wheer we query all the events from the DB related to an specific room and destroy all of them
  #In this way we assure that the DB is not full of events we dont need
  #Then we proceed to create the events
  def clear_and_create_events(event_hash, room)
    puts "Clearing and creating announcemnets for class: "+room.to_s
    selected_announcements_to_be_destroy = []
    begin 
      selected_announcements_to_be_destroy = Announcement.find_by_sql("SELECT * FROM announcements WHERE place = '#{room}'")
    rescue=>e
      print e.backtrace
    end
   
    puts "query size: "+selected_announcements_to_be_destroy.length.to_s
    destroy_selected_announcements(selected_announcements_to_be_destroy)
    create_classroom_announcement(event_hash, room)
    puts "Clearing and creating announcemnets for class: "+room.to_s+" went good!"
    return event_hash.clear
  end
  
  
  #Destroy a selcted set from the DB
  def destroy_selected_announcements announcements_array
    unless announcements_array.length == 0 then puts "Destroying events for class: "+announcements_array[0].place.to_s end
    announcements_array.each do |a|
      a.destroy
    end
  end

  #Destroy everything from the DB
  def destroy_all
    events = Announcement.find(:all)
       events.each do |event|
         event.destroy
     end
  end

  #Incharge of putting together the classroom announcement and save it in the DB
  def create_classroom_announcement (announcements, class_room)
    announcements.each do |event|
      current_announcement = Announcement.new
      current_announcement.announcement_type = $class_room_event
      current_announcement.title = event[1]["Title"]
   
      start_end_time = create_time_start_and_end(event[1]["When"])
      current_announcement.start = Time.parse(start_end_time[0])
      current_announcement.end = Time.parse(start_end_time[1])
 
      current_announcement.description = event[1]["Description"]
      current_announcement.place = class_room
      current_announcement.save
    end
  end
  
  #Same idea as for clear_and_create_events the only difference is that for the seminars we dont need the room
  def clear_and_create_seminars(event_hash)
    puts "Clearing and creating seminars "
    selected_announcements_to_be_destroy = []
    selected_announcements_to_be_destroy = Announcement.find_by_sql("SELECT * FROM announcements WHERE announcement_type = '#{$seminar_event}' or announcement_type = '#{$PhD_defense}' or announcement_type = '#{$Defense}' or announcement_type = '#{$General_event}' or announcement_type = '#{$PhD_seminar}'")
    puts "query size: "+selected_announcements_to_be_destroy.length.to_s
    destroy_selected_announcements(selected_announcements_to_be_destroy)
    create_seminar_announcement(event_hash)
    puts "Clearing and creating seminars went good!"
    return event_hash.clear
  end
  
  #Incharge of creating the seminar announcement. This is a little bit complicated since
  #We need to create a smart parser due to inconsstencies of the seminar information
  #Seminar by Michal Young - SI-007
  def create_seminar_announcement announcements
    announcements.each do |event|
     
      result = parse_seminar_title(event[1]["Title"])
      type_of_event = result[0][0]
      speaker_name = result[0][1]
      room = result[1].to_s

      current_announcement = Announcement.new
      current_announcement.announcement_type = type_of_event
      current_announcement.title = type_of_event+" by "+speaker_name
   
      start_end_time = create_time_start_and_end(event[1]["When"])
      current_announcement.start = Time.parse(start_end_time[0])
      current_announcement.end = Time.parse(start_end_time[1])
 
      current_announcement.description = event[1]["Description"]
      current_announcement.place = room
      
#      puts "**********************************"
#      puts "*"
#      puts "*   type => "+current_announcement.announcement_type
#      puts "*   title => "+current_announcement.title
#      puts "*   room => "+current_announcement.place
#      puts "*   start => "+current_announcement.start.to_s
#      puts "*   end => "+current_announcement.end.to_s
      
      current_announcement.save
    end
  end
  
  
  #Seminar Melucci
  #Seminar by Michal Young - SI-007
  #Seminar by Mounia Lalmas - room SI-008
  #PhD Defense of Lasaro Camargos
  #Seminar course for PhD - David Parnas - Room SI-006
  #Hard core name in the seminars this function has to be AI otherwise will break in the future since
  #some of the seminars are not really seminars there are also PhD defenses and seminar without
  #last name!!!
  #Inconsistence! this is ridiculous
  def parse_seminar_title title
    
    if(title.include?("-")) then title_array = title.split("-") else title_array = [] end
#    title_array = unless title.include?("-") == false then split("-") else [] end
    # Examples
    # 1- Seminar by Michal Young - SI-007
    # 2- Seminar course for PhD - David Parnas - Room SI-006
    if(title_array.length > 0) 
      room = ai_room_for_seminar(title_array[title_array.length-1])
        #Exmaple 2 
        if(title_array.length > 3) 
          for counter in 0..title_array.length-2  # dont go until the end since the end should be the room
            string_result += title_array[counter]+" "
          end
          type_name_array_result = ai_type_name_for_seminar(string_result)
        else
          #Example 1
          type_name_array_result = ai_type_name_for_seminar(title_array[0])
        end
    else
      type_name_array_result = ai_type_name_for_seminar(title)
      room = "NO-ROOM"
    end

     return [type_name_array_result, room]
  end
  
  
  #So far looking at the possible formats written in the calendar we notice that the last string is the room number
  def ai_room_for_seminar room
#    first_split = room_array.split(" ")
    result = room.split("-")
    return "SI-"+result[result.length-1]
  end
  
  #Seminar course for PhD - David Parnas - Room SI-006
  #PhD Defense of Lasaro Camargos
  def ai_type_name_for_seminar type_name
    
    if (type_name.include?("Seminar"))
       type = $seminar_event
    
    elsif(type_name.include?("Defense"))   
      if(type_name.include?("PhD"))
        type = $PhD_defense
      else
        type = $Defense
      end
    elsif(type_name.include?("PhD"))   
        type = $PhD_seminar
    else
      return [$General_event, 'USI']
    end
    
    split_result = type_name.split(" ")
    puts "========================================== "+split_result[split_result.length-1]
    #I noticed 2 problems 1) it can be only the name for that reason then 2) we check that the first on is not by otherwise
    #will repeat BY....example Seminar by by ???
    name = unless split_result.length <= 2 or split_result[split_result.length-2] == 'by' then split_result[split_result.length-2]+" "+split_result[split_result.length-1] else split_result[split_result.length-1] end 

    return [type, name]
  end
  
  
  #This is a general function to create the starting and finishing time of an announcement
  def create_time_start_and_end a_time
    time_array = a_time.split(" ")

    day_name = parse_german_day(time_array[0])    

    day = time_array[1].split(".")[0]
    month = Time.now.month
   # if(month < 10) then month = "0"+month.to_s else month = month.to_s end
    month = parse_german_month time_array[2]
    year = time_array[3]
    
    start_hour = time_array[4].split(":")
    start_min = start_hour[1]
    start_hour = start_hour[0]
    
    end_hour = time_array[6].split(":")
    end_min = end_hour[1]
    end_hour = end_hour[0]
    
    sec = "00"
    zone = time_array[7]
    
    start_date = day_name.to_s+" "+month.to_s+" "+day+" "+start_hour.to_s+":"+start_min.to_s+":"+sec+" "+zone+" "+year.to_s
    end_date = day_name.to_s+" "+month.to_s+" "+day+" "+end_hour.to_s+":"+end_min.to_s+":"+sec+" "+zone+" "+year.to_s
    return [start_date,end_date]
  end
  
  
  #Next 2 methods are to translate to German
  def parse_german_month month
    case month
      when "Jan" then return "Jan"
      when "Feb" then return "Feb"  
      when "Mär" then return "Mar"
      when "Mai" then return "May"
      when "Jun" then return "Jun"
      when "Jul" then return "Jul"
      when "Aug" then return "Aug"
      when "Sep" then return "Sep"
      when "Okt" then return "Oct"
      when "Nov" then return "Nov"
      when "Dez" then return "Dec"
      else return month
    end
  end
  
  def parse_german_day day
    case day
      when "Mo" then return "Mon"
      when "Di" then return "Tue"  
      when "Mi" then return "Wed"
      when "Do" then return "Thu"
      when "Fi" then return "Fri"
      when "Sa" then return "Sat"
      when "Di" then return "Sun"
      else return day
    end
    
  end

  #Here we are just reading the information located in an specific calendar.
  def readxml (calendarurl)
    current_time = Time.now
    month = current_time.month
    year = current_time.year.to_s
    day = current_time.day.to_s
    
    range_of_days_for_query = 30
    
    future_day = (current_time +range_of_days_for_query.days).day.to_s
    future_month = (current_time +range_of_days_for_query.days).month
    
    if (month < 10) then month = "0"+month.to_s 
  end
    if (future_month < 10) then future_month = "0"+future_month.to_s 
  end

    url = calendarurl+"?max-results=300&start-min="+year+
                                 "-"+month+"-"+day+"T01:00:00&start-max="+year+
                                 "-"+future_month+"-"+future_day+"T23:59:59&orderby=starttime&singleevents=true"
     
     result = Net::HTTP.get(URI(url))
     @doc = REXML::Document.new result

    titlearray =[]
    descarray = []
    counter = 0
    REXML::XPath.each( @doc, "//title") { |element| 
                                                    if(element.attributes["type"] == 'html') 
                                                    titlearray[counter] = element.text
                                                    counter +=1
                                                    end}
    counter = 0                                                
    REXML::XPath.each( @doc, "//content") { |element| 
                                                    descarray[counter] = element.text
                                                    counter +=1
                                                    }
                                           
    event_parser(titlearray,descarray)                                              
  end
  
  
end
